﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using App.Pay.WePay.XcxPay;
using Coldairarrow.Business;
using Coldairarrow.Entity;
using Coldairarrow.Entity.Backstage.TheRules;
using Coldairarrow.Entity.Backstage.UserData;
using Coldairarrow.Entity.BTB_StaffUsers;
using Coldairarrow.Entity.Goods;
using Coldairarrow.Entity.Pay;
using Coldairarrow.IBusiness.Pay;
using Coldairarrow.Util;
using Coldairarrow.Util.lib;
using EFCore.Sharding;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Serilog;
using ThoughtWorks.QRCode.Codec;
using WxPayAPI;

namespace Coldairarrow.Api.Controllers.Pay
{
  
    [Route("/Pay/[controller]/[action]")]
    [NoCheckJWT]
    public class WeChatPayController : BaseApiController
    {
        private IOrder_MasterBusiness _order_MasterBus { get; }
        private IOutbound_DetailsBusiness _outbound_DetailsBusiness { get; }
        private IWeChatParameterBusiness _weChatParameterBusiness { get; }
        public ILogger<WeChatPayController> _logger;
        private IDbAccessor _DB;

        public WeChatPayController(ILogger<WeChatPayController> logger, IDbAccessor db, IOrder_MasterBusiness order_MasterBus, IOutbound_DetailsBusiness outbound_DetailsBusiness, IWeChatParameterBusiness weChatParameterBusiness)
        {
            _outbound_DetailsBusiness = outbound_DetailsBusiness;
            _weChatParameterBusiness = weChatParameterBusiness;
            _order_MasterBus = order_MasterBus;
            _logger = logger;
            _DB = db;
        }
        #region 扫码支付

        /**
    * 生成直接支付url，支付url有效期为2小时,模式二
    * @param productId 商品ID
    * @return 模式二URL
    */
        [HttpPost]
        [NoCheckJWT]
        public Util.lib.PayNum GetPayUrl(string productDesc, string Orderid, double SumMoney, string ProductName)
        {
            Util.lib.PayNum payNum = new Util.lib.PayNum();
            var data1 = _DB.GetIQueryable<Order_Master>(true).Where(q => q.Id == Orderid && q.PayState == 0).ToList();

            if (data1.Count() > 0)
            {
                double money = SumMoney * 100;
                Serilog.Log.Information("使用扫码支付");
                var id = WxPayApi.GenerateOutTradeNo();
                WxPayData data = new WxPayData();
                data.SetValue("body", productDesc);//商品描述
                data.SetValue("attach", Orderid);//商品订单id
                string ff = id;
                data.SetValue("out_trade_no", ff);//随机字符串
                data.SetValue("total_fee", (int)money);//总金额
                data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));//交易起始时间
                data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));//交易结束时间
                data.SetValue("goods_tag", "jjj");//商品标记
                data.SetValue("trade_type", "NATIVE");//交易类型
                data.SetValue("product_id", ProductName);//商品名称
                List<Order_Master> aa = _DB.GetIQueryable<Order_Master>(true).Where(q => q.Id == Orderid).ToList();
                if (aa.Count <= 0)
                {

                    payNum.code = "-1";
                    payNum.msg = "订单内部出现异常，请联系管理员";
                    payNum.Success = false;
                    payNum.Data = null;
                    return payNum;
                }

                aa[0].ExternalOrder = id;
                _order_MasterBus.UpdateDataAsync(aa[0]);
                WxPayData result = WxPayApi.UnifiedOrder(data);//调用统一下单接口
                string url = result.GetValue("code_url").ToString();//获得统一下单接口返回的二维码链接

                Serilog.Log.Information("Get native pay mode 2 url : " + url);


                string str = url;

                //初始化二维码生成工具
                QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
                qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
                qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
                qrCodeEncoder.QRCodeVersion = 0;
                qrCodeEncoder.QRCodeScale = 10;

                //将字符串生成二维码图片
                Bitmap image = qrCodeEncoder.Encode(str, Encoding.Default);

                //保存为PNG到内存流  
                MemoryStream ms = new MemoryStream();
                image.Save(ms, ImageFormat.Jpeg);

                //输出二维码图片

                payNum.code = "200";
                payNum.msg = "操作成功";
                payNum.Success = true;
                payNum.Data = ms.GetBuffer();
                return payNum;
            }
            else
            {
                payNum.code = "202";
                payNum.msg = "该订单已被支付";
                payNum.Success = false;
                payNum.Data = null;
                return payNum;
            }
        }
       
        /// <summary>
        /// 回调
        /// </summary>
        /// <returns></returns>
        public async Task<ActionResult> OrderHuidiao()
        {
            using (var reader = new StreamReader(HttpContext.Request.Body))
            {


                var body = await reader.ReadToEndAsync();
                _logger.LogInformation("回调参数" + body);
                if (string.IsNullOrEmpty(body))
                {
                    return Content("<xml><return_code>FAIL</return_code><return_msg>支付失败</return_msg></xml>");
                }
                var xmlDoc = XDocument.Parse(body);

                _logger.LogInformation("订单号" + xmlDoc.Element("xml").Element("out_trade_no").Value);
                var out_trade_no = xmlDoc.Element("xml").Element("out_trade_no").Value;//商户订单号
                var _SumMoney = xmlDoc.Element("xml").Element("total_fee").Value;
                var _Orderid = xmlDoc.Element("xml").Element("attach").Value;
                var transaction_id = xmlDoc.Element("xml").Element("transaction_id").Value;

                _logger.LogInformation("外部订单号" + _Orderid);
                //在这写逻辑代码
                List<Order_Master> aa = _DB.GetIQueryable<Order_Master>(true).Where(q => q.Id == _Orderid).ToList();
                _logger.LogInformation("订单支付" + aa.Count);
                if (aa.Count <= 0)
                {
                    _logger.LogInformation("订单支付出现异常，请重新支付" + aa.Count);
                    throw new BusException("订单支付出现异常，请重新支付", errorCode: -1);
                }
                _logger.LogInformation("订单价格" + aa[0].TotalPrice);
                if (aa[0].TotalPrice != Convert.ToDecimal(_SumMoney) / 100)
                {
                    _logger.LogInformation("订单价格出现异常，请联系管理员" + aa[0].TotalPrice);
                    throw new BusException("订单价格出现异常，请联系管理员", errorCode: -1);
                }
                _logger.LogInformation("订单号" + aa[0].Id);
                if (aa[0].Id != _Orderid)
                {
                    _logger.LogInformation("订单号出现异常，请联系管理员" + aa[0].Id);
                    throw new BusException("订单号出现异常，请联系管理员", errorCode: -1);
                }
                if (aa[0].OrderState == 0)
                {
                    aa[0].OrderState = 1;
                    aa[0].PayState = 2;
                    aa[0].ExternalOrder = transaction_id;
                    await _order_MasterBus.UpdateDataAsync(aa[0]);
                }

                List<Outbound_Details> bb = _DB.GetIQueryable<Outbound_Details>(true).Where(q => q.OrderMater_Id == _Orderid).ToList();
                int count = bb.Count();
                _logger.LogInformation("参数量" + count);
                if (bb[0].Bound_Flag == 2)
                {
                    return Content("<xml><return_code>FAIL</return_code><return_msg>支付成功OK</return_msg></xml>");
                }
                if (count > 0)
                {
                    bb[0].Bound_Flag = 2;
                    await _outbound_DetailsBusiness.UpdateDataAsync(bb[0]);
                    if (_Orderid != null)
                    {
                        string key = RedisHelper.Get("Order:" + _Orderid);
                        RedisHelper.Del(key);
                    }
                    try
                    {
                        WeChatParameter data = new WeChatParameter()
                        {
                            Id = IdHelper.GetId(),
                            out_trade_no = out_trade_no,
                            _SumMoney = Convert.ToDecimal(_SumMoney) / 100,
                            _Orderid = _Orderid,
                            transaction_id = transaction_id,
                            PayMode = 2,
                            CreateTime = DateTime.Now
                        };
                        await _weChatParameterBusiness.AddDataAsync(data);
                    }
                    catch (Exception e)
                    {
                        _logger.LogInformation(e.Message.ToString());
                        throw e;
                    }

                    stock(_Orderid);
                    _logger.LogInformation("++++++++++++回调成功+++++++++++++++++++++");
                }
                _logger.LogInformation("++++++++++++回调失败+++++++++++++++++++++");
                return Content("<xml><return_code>FAIL</return_code><return_msg>支付成功OK</return_msg></xml>");
            }
        }
        #endregion

        #region 小程序支付
        /// <summary>
        /// 微信小程序支付
        /// </summary>
        /// <summary>
        /// 小程序下单
        /// </summary>
        /// <param name="input">openid</param>
        /// <returns></returns>
        [HttpPost]
        public object WeXcxPay(WechatPay input)
        {
            #region 验证订单是否有效,并合计价格
            var data1 = _DB.GetIQueryable<Order_Master>(true).Where(q => q.Id == input.oIds).ToList();

            if (data1.Count == 0)
            {
                throw new BusException("未查询到此订单请重新下单重试！");
            }
            else if (data1.Count > 0 && data1[0].PayState > 0)
            {
                throw new BusException("此订单已支付，请勿重新支付！");
            }

            input.payPrice = data1[0].TotalPrice;
            Serilog.Log.Information("Price={0}",input.payPrice.ToString());
            Serilog.Log.Information("oIds={0}", input.oIds.ToString());
            Serilog.Log.Information("openid={0}", input.openid.ToString());
            #endregion

            int payMoney = Convert.ToInt32(input.payPrice * 100);
            //int payMoney = 1;

            #region 统一下单
            if (data1.Count() > 0 && input.payPrice.HasValue && input.payPrice > 0)
            {
                try
                {
                    //支付回调通知地址
                    var notifyAddress = "https://api.leyi123.com/Pay/WeChatPay/WeXcxNotifyUrl";
                    WxPayData data = new WxPayData();
                    data.SetValue("body", "商品购买");

                    //可以将用户Id和订单Id同时封装在attach中
                    data.SetValue("attach", input.oIds);
                    Random rd = new Random();
                    //外部商户订单号
                    var payNum = DateTime.Now.ToString("yyyyMMddHHmmss") + rd.Next(0, 1000).ToString().PadLeft(3, '0');
                    data.SetValue("appid", WxPayConfig.GetConfig().GetAppID());//公众帐号id
                    data.SetValue("out_trade_no", payNum);
                    data.SetValue("detail", input.detail);
                    data.SetValue("total_fee", payMoney);
                    data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));
                    data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));
                    data.SetValue("notify_url", notifyAddress);
                    //data.SetValue("goods_tag", "test");
                    data.SetValue("trade_type", "JSAPI");
                    data.SetValue("openid", input.openid);
                    List<Order_Master> aa = _DB.GetIQueryable<Order_Master>(true).Where(q => q.Id == input.oIds && q.PayState != 1 && q.TotalPrice == Convert.ToDecimal(input.payPrice) && q.PayState == 0).ToList();
                    if (aa.Count <= 0)
                    {
                        throw new BusException("订单内部出现异常，请联系管理员", errorCode: -1);
                    }
                    aa[0].ExternalOrder = payNum;
                    _order_MasterBus.UpdateDataAsync(aa[0]);
                    WxPayData result = WxPayApi.UnifiedOrder(data);//调用统一下单接口
                    if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "")
                    {
                        _logger.LogInformation(this.GetType().ToString(), "预下单失败");
                        throw new WxPayException("UnifiedOrder response error!");
                    }


                    var timeStamp = ((DateTime.Now.Ticks - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).Ticks) / 10000).ToString();
                    string nonce_str = result.GetValue("nonce_str").ToString();
                    string package = "prepay_id=" + result.GetValue("prepay_id").ToString();
                    var signType = "MD5";
                    var flag = true;
                    var msg = "下单成功";
                    var appId = WxPayConfig.GetConfig().GetAppID();
                    XcxPayData applet = new XcxPayData();
                    applet.SetValue("appId", appId);
                    applet.SetValue("nonceStr", nonce_str);
                    applet.SetValue("package", package);
                    applet.SetValue("signType", signType);
                    applet.SetValue("timeStamp", timeStamp);
                    var appletSign = applet.MakeSign();
                    _logger.LogInformation(timeStamp + nonce_str + signType + appletSign + flag + msg + "预下单成功");
                    return (new { timeStamp, nonce_str, package, signType, paySign = appletSign, Result = flag, msg });
                }
                catch (Exception ex)
                {
                    Serilog.Log.Error(ex.ToJson().ToString());
                    Serilog.Log.Error(ex.Message);
                    return (new { Result = false, msg = "缺少参数" });
                }
            }
            else
            {
                return (new { Result = false, msg = "该订单已被支付" });
            }
            #endregion

        }
     
        /// <summary>
        /// 微信小程序支付回调通知
        //</summary>
        //<returns></returns>
        public async Task<ActionResult> WeXcxNotifyUrl()
        {
            _logger.LogInformation("小程序支付开始回调");
            var k = HttpContext.Request.Body;
            using (var reader = new StreamReader(k))
            {

                var body = await reader.ReadToEndAsync();
                _logger.LogInformation("回调参数" + body);
                if (string.IsNullOrEmpty(body))
                {
                    return Content("<xml><return_code>FAIL</return_code><return_msg>支付失败</return_msg></xml>");
                }
                var xmlDoc = XDocument.Parse(body);

                _logger.LogInformation("订单号" + xmlDoc.Element("xml").Element("out_trade_no").ToString());
                //微信订单号
                var _transaction_id = xmlDoc.Element("xml").Element("transaction_id").Value;
                //自定义订单号
                var _out_trade_no = xmlDoc.Element("xml").Element("out_trade_no").Value;
                //返回code码
                var _return_code = xmlDoc.Element("xml").Element("return_code").Value;
                //身份证
                var _attach = xmlDoc.Element("xml").Element("attach").Value;
                //交易结束时间
                var _time_end = xmlDoc.Element("xml").Element("time_end").Value;
                //支付金额
                var _total_fee = xmlDoc.Element("xml").Element("total_fee").Value;

                //检查支付结果中transaction_id是否存在
                if (_transaction_id.IsNullOrEmpty())
                {
                    //若transaction_id不存在，则立即返回结果给微信支付后台
                    XcxPayData res = new XcxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "支付结果中微信订单号不存在");
                    Serilog.Log.Information(this.GetType().ToString(), "+++++++++++++++++++++The Pay result is error : " + res.ToXml());
                   
                    return Content("<xml><return_code>FAIL</return_code><return_msg>支付结果中微信订单号不存在</return_msg></xml>", "/index.html");
                }

                //查询订单，判断订单真实性
                if (!XcxQueryOrder(_transaction_id))
                {
                    //若订单查询失败，则立即返回结果给微信支付后台
                    XcxPayData res = new XcxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "订单查询失败");
                    Serilog.Log.Information(this.GetType().ToString(), "++++++++++++++++++++Order query failure : " + res.ToXml());

                    return Content("<xml><return_code>FAIL</return_code><return_msg>订单查询失败</return_msg></xml>", "/index.html");

                }
                //查询订单成功
                else
                {
                    List<Order_Master> aa = _DB.GetIQueryable<Order_Master>(true).Where(q => q.ExternalOrder == xmlDoc.Element("xml").Element("out_trade_no").Value).ToList();
                    XcxPayData res = new XcxPayData();
                    res.SetValue("return_code", "SUCCESS");
                    res.SetValue("return_msg", "OK");
                    Serilog.Log.Information(this.GetType().ToString(), "Order query success : " + res.ToXml());
                    var returnCode = _return_code;
                    var transactionNo = _transaction_id;//微信订单号
                    var outTradeNo = _out_trade_no;//自定义订单号
                    var attach = _attach;//身份证
                    _logger.LogInformation("订单号" + attach);
                    var endTime = _time_end;//交易结束时间
                    var totalFee = _total_fee; ;//支付金额
                    aa[0].OrderState = 1;
                    aa[0].PayState = 2;
                    aa[0].ExternalOrder = _transaction_id;
                    _DB.Update<Order_Master>(aa[0]);
                    List<Outbound_Details> bb = _DB.GetIQueryable<Outbound_Details>(true).Where(q => q.OrderMater_Id == _attach).ToList();
                    bb[0].Bound_Flag = 2;

                    await _outbound_DetailsBusiness.UpdateDataAsync(bb[0]);
                    WeChatParameter data = new WeChatParameter()
                    {
                        Id = IdHelper.GetId(),
                        out_trade_no = outTradeNo,
                        _SumMoney = Convert.ToDecimal(_total_fee),
                        _Orderid = _attach,
                        transaction_id = _transaction_id,
                        PayMode = 3,
                        CreateTime = DateTime.Now
                    };
                    await _weChatParameterBusiness.AddDataAsync(data);
                    await  stock(_attach);
                    _logger.LogInformation("+回调成功+");
                    var result = true;

                    #region//分销代码
                    //查询上级人员
                    var theUser = _DB.GetIQueryable<BTB_StaffUser>().Where(x => x.id.Equals(aa[0].CreatorId)).ToList();
                    if (theUser.Count > 0)
                    {
                        var sjUser = _DB.GetIQueryable<BTB_StaffUser>().Where(x => x.User_YQCode.Equals(theUser[0].User_BYQCode)).ToList();
                        if (sjUser.Count > 0)
                        {
                            //获取所有商品
                            var gList = _DB.GetIQueryable<Order_Decimal>().Where(x => x.OrderMaster_Id.Equals(aa[0].Id)).ToList();
                            int syNum = 0;

                            //查询默认返利折扣
                            int dsCount = 0;
                            var dfList = _DB.GetIQueryable<BS_Rebate>().Where(x => x.GoodsId.Equals("****") && x.IsDefault).ToList();
                            if (dfList.Count > 0)
                            {
                                dsCount = (int)dfList[0].ReturnDiscount;
                            }
                            List<BS_UserRebate> uList = new List<BS_UserRebate>();
                            foreach (var item in gList)
                            {
                                //查询商品返利折扣
                                var dgfList = _DB.GetIQueryable<BS_Rebate>().Where(x => x.GoodsId.Equals(item.Product_Id) && x.IsDefault).ToList();
                                if (dgfList.Count > 0)
                                {
                                    dsCount = (int)dgfList[0].ReturnDiscount;
                                }

                                if (dsCount > 0)
                                {
                                    int rMoney = (int)(((decimal)item.SumProducts * dsCount) / 100);
                                    if (rMoney > 0)
                                    {
                                        BS_UserRebate model = new BS_UserRebate();
                                        model.Id = IdHelper.GetId();
                                        model.Deleted = false;
                                        model.CreatorId = theUser[0].id;
                                        model.CreateTime = DateTime.Now;
                                        model.SUserId = sjUser[0].id;
                                        model.XFUserId = theUser[0].id;
                                        model.OrderId = aa[0].Id;
                                        model.GoodsId = item.Products_Id;
                                        model.ReturnDiscount = dsCount;
                                        model.OrderMoney = (decimal)item.SumProducts;
                                        model.GoodsName = item.ProductNames;
                                        model.GoodsItemName = item.ProductitemNames;
                                        model.GoodsPrice = item.ProductPrice;
                                        model.GoodsNum = item.Products_Num;
                                        model.Note = theUser[0].NickName.Substring(0, 1) + "*购买" + item.ProductitemNames + "收益";
                                        model.Type = 0;
                                        model.ReturnMoney = rMoney;
                                        syNum += rMoney;
                                        uList.Add(model);
                                    }
                                    
                                    var upMList = _DB.GetIQueryable<BS_UserICPoint>().Where(x => x.UserId.Equals(sjUser[0].id)).ToList();
                                    if (upMList.Count > 0)
                                    {
                                        upMList[0].Income += syNum;

                                        await _DB.UpdateAsync(upMList[0]);
                                        await _DB.InsertAsync(uList);
                                    }
                                    else
                                    {
                                        BS_UserICPoint upModel = new BS_UserICPoint();
                                        upModel.Id = IdHelper.GetId();
                                        upModel.Deleted = false;
                                        upModel.CreatorId = theUser[0].id;
                                        upModel.CreateTime = DateTime.Now;
                                        upModel.UserId = sjUser[0].id;
                                        upModel.Income = syNum;
                                        upModel.Point = 0;

                                        await _DB.InsertAsync(upModel);
                                        await _DB.InsertAsync(uList);
                                    }


                                }
                               
                            }
                                 

                        }
                    }

                    #endregion

                    Serilog.Log.Information(this.GetType().ToString(), "CompleteWePay:" + result);

                    return Content("<xml><return_code>FAIL</return_code><return_msg>支付成功OK</return_msg></xml>", "/index.html");

                }
            }
        }


        /// <summary>
        /// 查询订单
        /// </summary>
        /// <param name="transaction_id">微信交易订单号</param>
        /// <returns></returns>
        private bool XcxQueryOrder(string transaction_id)
        {
            XcxPayData req = new XcxPayData();
            req.SetValue("transaction_id", transaction_id);
            XcxPayData res = XcxPayApi.OrderQuery(req);
            if (res.GetValue("return_code").ToString() == "SUCCESS" && res.GetValue("result_code").ToString() == "SUCCESS")
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion

        #region 公众号支付
        /// <summary>
        /// 微信小程序支付
        /// </summary>
        /// <summary>
        /// 小程序下单
        /// </summary>
        /// <param name="input">openid</param>
        /// <returns></returns>
        [HttpPost]
        public object WeGzhPay(WechatPay input)
        {
            #region 验证订单是否有效,并合计价格
            var data1 = _DB.GetIQueryable<Order_Master>(true).Where(q => q.Id == input.oIds).ToList();

            if (data1.Count == 0)
            {
                throw new BusException("未查询到此订单请重新下单重试！");
            }
            else if (data1.Count > 0 && data1[0].PayState > 0)
            {
                throw new BusException("此订单已支付，请勿重新支付！");
            }

            Serilog.Log.Information("开启微信公众号支付==========》");
            Serilog.Log.Information("WXGZHZF->input.oIds={0}",input.oIds);
            Serilog.Log.Information("WXGZHZF->input.oIds={0}", input.openid);
            Serilog.Log.Information("WXGZHZF->input.oIds={0}", input.detail);
            input.payPrice = data1[0].TotalPrice;

            Serilog.Log.Information("WXGZHZF->input.payPrice={0}", Convert.ToInt32(input.payPrice * 100));
            #endregion

            #region 统一下单
            if (data1.Count() > 0 && input.payPrice.HasValue && input.payPrice > 0)
            {
                try
                {
                    //支付回调通知地址
                    var notifyAddress = "https://api.leyi123.com/Pay/WeChatPay/WeGzhNotifyUrl";
                    WxPayData data = new WxPayData();
                    data.SetValue("body", "商品购买");

                    int payMoney = Convert.ToInt32(input.payPrice * 100);
                    //int payMoney = 1;

                    //可以将用户Id和订单Id同时封装在attach中
                    data.SetValue("attach", input.oIds);
                    Random rd = new Random();
                    //外部商户订单号
                    var payNum = DateTime.Now.ToString("yyyyMMddHHmmss") + rd.Next(0, 1000).ToString().PadLeft(3, '0');
                    data.SetValue("appid", WxPayGZHConfig.GetConfig().GetAppID());//公众帐号id
                    data.SetValue("out_trade_no", payNum);
                    data.SetValue("detail", input.detail);
                    data.SetValue("total_fee", payMoney);
                    data.SetValue("time_start", DateTime.Now.ToString("yyyyMMddHHmmss"));
                    data.SetValue("time_expire", DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss"));
                    data.SetValue("notify_url", notifyAddress);
                    //data.SetValue("goods_tag", "test");
                    data.SetValue("trade_type", "JSAPI");
                    data.SetValue("openid", input.openid);
                    //价格对比
                    List<Order_Master> aa = _DB.GetIQueryable<Order_Master>(true).Where(q => q.Id == input.oIds && q.PayState != 1 && q.TotalPrice == Convert.ToDecimal(input.payPrice) && q.PayState == 0).ToList();
                    if (aa.Count <= 0)
                    {
                        throw new BusException("订单内部出现异常，请联系管理员", errorCode: -1);
                    }
                    aa[0].ExternalOrder = payNum;
                    _order_MasterBus.UpdateDataAsync(aa[0]);
                    WxPayData result = WxGZHPayApi.UnifiedOrder(data);//调用统一下单接口
                    if (!result.IsSet("appid") || !result.IsSet("prepay_id") || result.GetValue("prepay_id").ToString() == "")
                    {
                        _logger.LogInformation(this.GetType().ToString(), "预下单失败");
                        throw new WxPayException("UnifiedOrder response error!");
                    }


                    var timeStamp = ((DateTime.Now.Ticks - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).Ticks) / 10000).ToString();
                    string nonce_str = result.GetValue("nonce_str").ToString();
                    string package = "prepay_id=" + result.GetValue("prepay_id").ToString();
                    var signType = "MD5";
                    var flag = true;
                    var msg = "下单成功";
                    var appId = WxPayGZHConfig.GetConfig().GetAppID();
                    XcxPayData applet = new XcxPayData();
                    applet.SetValue("appId", appId);
                    applet.SetValue("nonceStr", nonce_str);
                    applet.SetValue("package", package);
                    applet.SetValue("signType", signType);
                    applet.SetValue("timeStamp", timeStamp);
                    var appletSign = applet.MakeGzhSign();
                    _logger.LogInformation(timeStamp + nonce_str + signType + appletSign + flag + msg + "预下单成功");
                    return (new { timeStamp, nonce_str, package, signType, paySign = appletSign, Result = flag, msg });
                }
                catch (Exception ex)
                {
                    return (new { Result = false, msg = "缺少参数" });
                }
            }
            else
            {
                return (new { Result = false, msg = "该订单已被支付" });
            }
            #endregion

        }

        /// <summary>
        /// 微信公众号支付回调通知
        ///</summary>
        ///<returns></returns>
        public async Task<ActionResult> WeGzhNotifyUrl()
        {
            _logger.LogInformation("公众号支付开始回调");
            var k = HttpContext.Request.Body;
            using (var reader = new StreamReader(k))
            {

                var body = await reader.ReadToEndAsync();
                _logger.LogInformation("回调参数" + body);
                if (string.IsNullOrEmpty(body))
                {
                    return Content("<xml><return_code>FAIL</return_code><return_msg>支付失败</return_msg></xml>");
                }
                var xmlDoc = XDocument.Parse(body);

                _logger.LogInformation("订单号" + xmlDoc.Element("xml").Element("out_trade_no").ToString());
                //微信订单号
                var _transaction_id = xmlDoc.Element("xml").Element("transaction_id").Value;
                //自定义订单号
                var _out_trade_no = xmlDoc.Element("xml").Element("out_trade_no").Value;
                //返回code码
                var _return_code = xmlDoc.Element("xml").Element("return_code").Value;
                //身份证
                var _attach = xmlDoc.Element("xml").Element("attach").Value;
                //交易结束时间
                var _time_end = xmlDoc.Element("xml").Element("time_end").Value;
                //支付金额
                var _total_fee = xmlDoc.Element("xml").Element("total_fee").Value;

                //检查支付结果中transaction_id是否存在
                if (_transaction_id.IsNullOrEmpty())
                {
                    //若transaction_id不存在，则立即返回结果给微信支付后台
                    XcxPayData res = new XcxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "支付结果中微信订单号不存在");
                    Serilog.Log.Information(this.GetType().ToString(), "+++++++++++++++++++++The Pay result is error : " + res.ToXml());
                    return Content("<xml><return_code>FAIL</return_code><return_msg>支付结果中微信订单号不存在</return_msg></xml>", "/index.html");
                }

                //查询订单，判断订单真实性
                if (!GzhQueryOrder(_transaction_id))
                {
                    //若订单查询失败，则立即返回结果给微信支付后台
                    XcxPayData res = new XcxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "订单查询失败");
                    Serilog.Log.Information(this.GetType().ToString(), "++++++++++++++++++++Order query failure : " + res.ToXml());

                    return Content("<xml><return_code>FAIL</return_code><return_msg>订单查询失败</return_msg></xml>", "/index.html");

                }
                //查询订单成功
                else
                {
                    List<Order_Master> aa = _DB.GetIQueryable<Order_Master>(true).Where(q => q.ExternalOrder == xmlDoc.Element("xml").Element("out_trade_no").Value).ToList();
                    XcxPayData res = new XcxPayData();
                    res.SetValue("return_code", "SUCCESS");
                    res.SetValue("return_msg", "OK");
                    Serilog.Log.Information(this.GetType().ToString(), "Order query success : " + res.ToXml());
                    var returnCode = _return_code;
                    var transactionNo = _transaction_id;//微信订单号
                    var outTradeNo = _out_trade_no;//自定义订单号
                    var attach = _attach;//身份证
                    _logger.LogInformation("订单号" + attach);
                    var endTime = _time_end;//交易结束时间
                    var totalFee = _total_fee; ;//支付金额
                    aa[0].OrderState = 1;
                    aa[0].PayState = 3;
                    aa[0].ExternalOrder = _transaction_id;
                    _DB.Update<Order_Master>(aa[0]);
                    List<Outbound_Details> bb = _DB.GetIQueryable<Outbound_Details>(true).Where(q => q.OrderMater_Id == _attach).ToList();
                    bb[0].Bound_Flag = 2;

                    await _outbound_DetailsBusiness.UpdateDataAsync(bb[0]);
                    WeChatParameter data = new WeChatParameter()
                    {
                        Id = IdHelper.GetId(),
                        out_trade_no = outTradeNo,
                        _SumMoney = Convert.ToDecimal(_total_fee),
                        _Orderid = _attach,
                        transaction_id = _transaction_id,
                        PayMode = 3,
                        CreateTime = DateTime.Now
                    };
                    await _weChatParameterBusiness.AddDataAsync(data);
                    await stock(_attach);
                    _logger.LogInformation("+回调成功+");
                    var result = true;

                    #region//分销代码
                    //查询上级人员
                    var theUser = _DB.GetIQueryable<BTB_StaffUser>().Where(x => x.id.Equals(aa[0].CreatorId)).ToList();
                    if (theUser.Count > 0)
                    {
                        var sjUser = _DB.GetIQueryable<BTB_StaffUser>().Where(x => x.User_YQCode.Equals(theUser[0].User_BYQCode)).ToList();
                        if (sjUser.Count > 0)
                        {
                            //获取所有商品
                            var gList = _DB.GetIQueryable<Order_Decimal>().Where(x => x.OrderMaster_Id.Equals(aa[0].Id)).ToList();
                            int syNum = 0;

                            //查询默认返利折扣
                            int dsCount = 0;
                            var dfList = _DB.GetIQueryable<BS_Rebate>().Where(x => x.GoodsId.Equals("****") && x.IsDefault).ToList();
                            if (dfList.Count > 0)
                            {
                                dsCount = (int)dfList[0].ReturnDiscount;
                            }
                            List<BS_UserRebate> uList = new List<BS_UserRebate>();
                            foreach (var item in gList)
                            {
                                //查询商品返利折扣
                                var dgfList = _DB.GetIQueryable<BS_Rebate>().Where(x => x.GoodsId.Equals(item.Product_Id) && x.IsDefault).ToList();
                                if (dgfList.Count > 0)
                                {
                                    dsCount = (int)dgfList[0].ReturnDiscount;
                                }

                                if (dsCount > 0)
                                {
                                    int rMoney = (int)(((decimal)item.SumProducts * dsCount) / 100);
                                    if (rMoney > 0)
                                    {
                                        BS_UserRebate model = new BS_UserRebate();
                                        model.Id = IdHelper.GetId();
                                        model.Deleted = false;
                                        model.CreatorId = theUser[0].id;
                                        model.CreateTime = DateTime.Now;
                                        model.SUserId = sjUser[0].id;
                                        model.XFUserId = theUser[0].id;
                                        model.OrderId = aa[0].Id;
                                        model.GoodsId = item.Products_Id;
                                        model.ReturnDiscount = dsCount;
                                        model.OrderMoney = (decimal)item.SumProducts;
                                        model.GoodsName = item.ProductNames;
                                        model.GoodsItemName = item.ProductitemNames;
                                        model.GoodsPrice = item.ProductPrice;
                                        model.GoodsNum = item.Products_Num;
                                        model.Note = theUser[0].NickName.Substring(0, 1) + "*购买" + item.ProductitemNames + "收益";
                                        model.Type = 0;
                                        model.ReturnMoney = rMoney;
                                        syNum += rMoney;
                                        uList.Add(model);
                                    }

                                    var upMList = _DB.GetIQueryable<BS_UserICPoint>().Where(x => x.UserId.Equals(sjUser[0].id)).ToList();
                                    if (upMList.Count > 0)
                                    {
                                        upMList[0].Income += syNum;

                                        await _DB.UpdateAsync(upMList[0]);
                                        await _DB.InsertAsync(uList);
                                    }
                                    else
                                    {
                                        BS_UserICPoint upModel = new BS_UserICPoint();
                                        upModel.Id = IdHelper.GetId();
                                        upModel.Deleted = false;
                                        upModel.CreatorId = theUser[0].id;
                                        upModel.CreateTime = DateTime.Now;
                                        upModel.UserId = sjUser[0].id;
                                        upModel.Income = syNum;
                                        upModel.Point = 0;

                                        await _DB.InsertAsync(upModel);
                                        await _DB.InsertAsync(uList);
                                    }


                                }

                            }


                        }
                    }

                    #endregion

                    Serilog.Log.Information(this.GetType().ToString(), "CompleteWePay:" + result);

                    return Content("<xml><return_code>FAIL</return_code><return_msg>支付成功OK</return_msg></xml>", "/index.html");

                }
            }
        }

        /// <summary>
        /// 查询订单
        /// </summary>
        /// <param name="transaction_id">微信交易订单号</param>
        /// <returns></returns>
        private bool GzhQueryOrder(string transaction_id)
        {
            XcxPayData req = new XcxPayData();
            req.SetValue("transaction_id", transaction_id);
            XcxPayData res = GzhPayApi.OrderQuery(req);
            if (res.GetValue("return_code").ToString() == "SUCCESS" && res.GetValue("result_code").ToString() == "SUCCESS")
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        #endregion

        public async Task stock(string id)
        {
            _logger.LogInformation("库存修改:" + id);
            var data = _DB.GetIQueryable<Order_Decimal>(true).Where(q => q.OrderMaster_Id == id).ToList();
            _logger.LogInformation("商品数据" + data.Count);
            foreach (var item in data)
            {
                var aa = item.Product_Id;
                _logger.LogInformation("商品+++++++++++++id" + aa);
                var Product = _DB.GetIQueryable<BTB_Goods>(true).FirstOrDefault(q => q.ID == item.Product_Id);
                _logger.LogInformation("回调成功+++++++++++++++++++++++" + Product);
                var Products = _DB.GetIQueryable<BTB_GoodsSpecificationsItem>(true).FirstOrDefault(q => q.GoodsSpecificationsItemID == item.Products_Id);
                _logger.LogInformation("回调成功+++++++++++++++++++++++" + Products);
                Product.SaleCount += (int)item.Products_Num;
                _logger.LogInformation("回调增加销量成功+++++++++++++++++++++++" + Product.SaleCount);
                if (!Products.IsNullOrEmpty())
                {
                    Products.Inventory = (int)Products?.Inventory - (int)item?.Products_Num;
                    _logger.LogInformation("回调修改库存成功+++++++++++++++++++++++" + Products.Inventory);
                    await _DB.UpdateAsync<BTB_GoodsSpecificationsItem>(Products);
                }
                await _DB.UpdateAsync<BTB_Goods>(Product);
            }
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [HttpPost]
        [NoCheckJWT]
        public async Task add(WeChatParameter data)
        {
            await _weChatParameterBusiness.AddDataAsync(data);
        }


        public static string out_refund_no = string.Empty;
        /// <summary>
        /// 退款
        /// </summary>
        /// <param name="transaction_id"></param>
        /// <param name="out_trade_no">订单id</param>
        /// <param name="total_fee">订单总金额</param>
        /// <param name="refund_fee">退款金额</param>
        /// <returns></returns>
        [HttpPost]
        [NoCheckJWT]
        public object WeXcxPay1(string transaction_id, int total_fee, int refund_fee)
        {
            #region 验证订单是否有效,并合计价格

            #endregion

            #region 统一退款

            Util.lib.PayNum payNum = new Util.lib.PayNum();
            var data1 = _DB.GetIQueryable<Order_Master>(true).Where(q => q.Id == out_refund_no && q.PayState == 0).ToList();
            try
            {

                Serilog.Log.Information("使用扫码支付");
                WxPayData data = new WxPayData();
                data.SetValue("total_fee", total_fee);//订单总金额
                data.SetValue("refund_fee", refund_fee);//退款金额
                data.SetValue("transaction_id", transaction_id);//退款金额
                data.SetValue("out_refund_no", WxPayApi.GenerateOutTradeNo());//随机生成商户退款单号
                data.SetValue("op_user_id", WxPayConfig.GetConfig().GetMchID());//操作员，默认为商户号
                WxPayData result = WxPayApi.Refund(data,"");//提交退款申请给API，接收返回数据
                var result_code = result.GetValue("result_code");
                var return_code = result.GetValue("return_code");
                var err_code_des = result.GetValue("err_code_des");

                return result;
            }
            #endregion
            catch (Exception ex)
            {
                _logger.LogInformation("ApplyRefund", ex);
                throw;
            }
        }
    }
}
